{% extends "tutorial.html" %}

{% block head %}
<style>
.talkinghead:before {
  background-image: url(/static/images/profiles/75/petele.75.png);
  background-position: 0px 0px !important;
}

.relevantCode {
  border-bottom: 1px solid #ccc;
}

table thead {
  background-color: #eeeee9;
  font-weight: bold;
}

table tr:nth-child(even) {
  background-color: #f7f7f9;
}

table td:first-of-type {
  width: 30%;
}

h4 {
  margin-top: 20px !important;
  margin-bottom: 0px !important;
}

.hidden {
  display: none !important;
}

</style>
{% endblock %}

{% block iscompatible %}
  return Modernizr.video;
{% endblock %}

{% block pagebreadcrumb %}{{ tut.title }}{% endblock %}

{% block content %}

  <h2 id="toc-intro">Introduction</h2>

  <p>
    In modern browsers, adding a video to your page is as easy as adding 
    an image.  No longer do you need to deal with special plug-ins or require
    crazy markup, you can do it with a single element.
  </p>

  <h2 id="toc-markup">The Markup</h2>

  <p>Let's jump in with a really simple example:</p>

  <pre class="prettyprint"><code>&lt;video src="video.webm" controls&gt;<br>&lt;/video&gt;</code></pre>

  <p>
    That's all you need to embed a simple video on your page and show the 
    basic controls so that a user can play, pause or otherwise control the video.
  </p>

  <h3 id="toc-spec-sources">Specifying Sources</h3>

  <p>
    You can specify multiple source files by using the <code>&lt;source&gt;</code> 
    element.  The source element lets you specify multiple formats as a 
    fallback in case the user's browser doesn't support one of them.  
    For example:
  </p>

  <pre class="prettyprint"><code>&lt;video controls&gt;
  &lt;source src="devstories.webm" 
          type='video/webm;codecs="vp8, vorbis"'/&gt;
  &lt;source src="devstories.mp4"
          type='video/mp4;codecs="avc1.42E01E, mp4a.40.2"'/&gt;
&lt;/video&gt;</code></pre>

  <p>
    When the browser parses the <code>&lt;source&gt;</code> tag, it uses the
    optional type attribute to help decide which file to download and play. 
    If the browser supports WebM and has the VP8 and Vorbis codecs, it will 
    play <code>devstories.webm</code>, if not, it will check if it can play 
    MPEG-4 videos with the avc1.42E01E and mp4a.40.2 codecs, and so forth.
  </p>

  <blockquote class="commentary talkinghead">
    To improve performance, you should always include
    the <code>type</code> attribute in the <code>source</code> element.  
    Otherwise the browser will need to load each video file until it can find
    one that it can play!
  </blockquote>

  <p>
    It's also a good idea to make sure that your videos are being served 
    with the right MIME type.  In some cases, the browser won't play the 
    video if the MIME type isn't set properly.
  </p>

  <h4>Media Fragments</h4>

  <p>
    Adding a <a href="http://www.w3.org/TR/media-frags/#naming-time">media
    fragment</a> to the media URL, you can specify the 
    <a href="http://simpl.info/mediafragments/">exact portion you want to 
    play</a>.  To add a media fragment, you simply add 
    <code>#t=[start_time][,end_time]</code> to the media URL. For example, 
    to play the video between seconds 10 through 20, you could specify:
  </p>

  <pre class="prettyprint"><code>&lt;source src="devstories.webm<b class="relevantCode">#t=10,20</b>" 
        type='video/webm;codecs="vp8, vorbis"' /&gt;</code></pre>

  <p>
    You can also specify the times in <code>hours:minutes:seconds</code>, 
    such as <code>#t=00:01:05</code> to start the video at one minute, five 
    seconds in.  Or, to only play the first minute of the video, you would 
    specify <code>#t=,00:01:00</code>.  You need to make sure Range Requests 
    are supported by your server: check for <code>Accept Ranges: bytes</code>. 
    It's on by default for Apache and many other servers, but worth checking.
  </p>

  <h3 id="toc-captions">Providing captions and subtitles</h3>

  <p>
    The <code>&lt;track&gt;</code> element provides a simple, standardized 
    way to add subtitles, captions, screen reader descriptions and chapters 
    to your video, which improves accessibility but also makes it possible 
    for search engines to understand what's in the video.  As well as 
    subtitles and captions, it's possible to put metadata in cues, for 
    example in JSON format. This can enable innovative use cases such as 
    <a href="http://simpl.info/map">DOM manipulation synchronised with video 
    playback</a>.
  </p>

  <video controls style="width:640px;height:360px;" poster="poster.png">
    <source src="devstories.webm" type='video/webm;codecs="vp8, vorbis"' />
    <source src="devstories.mp4" type='video/mp4;codecs="avc1.42E01E, mp4a.40.2"' />
    <track src="devstories-en.vtt" label="English subtitles" kind="subtitles" srclang="en" default></track>
  </video>

<pre class="prettyprint"><code>&lt;video controls style="width:640px;height:360px;" poster="poster.png"&gt;
  &lt;source src="devstories.webm" 
          type='video/webm;codecs="vp8, vorbis"' /&gt;
  &lt;source src="devstories.mp4" 
          type='video/mp4;codecs="avc1.42E01E, mp4a.40.2"' /&gt;
  <b>&lt;track src="devstories-en.vtt" label="English subtitles" 
         kind="subtitles" srclang="en" default&gt;&lt;/track&gt;</b>
&lt;/video&gt;</code></pre>

  <p>
    The <code>&lt;track&gt;</code> element functions like a 
    <code>&lt;source&gt;</code> element within the <code>&lt;video&gt;</code>
    element, and has a <code>src</code> attribute that points to a file in 
    <a href="http://html5doctor.com/video-subtitling-and-webvtt/#contents">
    WebVTT format</a>.  You can specify the <code>label</code> that will be 
    displayed in the UI to the user, as well as the source language 
    (<code>srclang</code>) and if there are multiple track elements, which 
    one should be used as the default.
  </p>

  <p>
    Here's the first few lines of <a href="devstories-en.vtt">devstories-en.vtt</a>:
  </p>

  <pre class="prettyprint"><code>WEBVTT FILE

1
00:00:00.500 --> 00:00:02.000 D:vertical A:start
The Web is always changing

2
00:00:02.500 --> 00:00:04.300
and the way we access it is changing

3
00:00:05.000 --> 00:00:07.000
The source of that change is &lt;c.highlight&gt;you&lt;/c&gt;</code></pre>

  <p>
    Check out <a href="http://www.html5rocks.com/tutorials/track/basics/">
    Getting Started With The Track Element</a> for more information.
  </p>

  <h3 id="toc-attributes">Attributes</h3>

  <p>
    The <code>&lt;video&gt;</code> element has several special attributes 
    that can change or enhance its default behavior.
  </p>

  <table>
    <tbody>
      <tr>
        <td><code>autoplay</code>*</td>
        <td>
          Tells the browser to immediately start downloading the video and play
          it as soon as it can.  Note that mobile browsers generally do not
          support this attribute, the user must tap the screen to begin video
          playback.
        </td>
      </tr>
      <tr>
        <td><code>preload</code></td>
        <td>
          <p>
            Hint to the browser about whether optimistic downloading of the 
            video itself or its metadata is considered worthwhile.
          </p>
          <p>Options are:</p>
          <ul>
            <li>
              <b><code>none</code></b> - Hints to the browser that the user 
              likely will not watch the video, or that minimizing unnecessary 
              traffic is desirable.
            </li>
            <li>
              <b><code>metadata</code></b> - Hints to the browser that the user 
              is not expected to need the video, but that fetching its metadata 
              (dimensions, first frame, track list, duration, and so on) is 
              desirable.
            </li>
            <li>
              <b><code>auto</code></b> - Hints to the browser that 
              optimistically downloading the entire video is considered 
              desirable.
            </li>
          </ul>
        </td>
      </tr>
      <tr>
        <td><code>poster</code></td>
        <td>Provides an image to show before the video loads</td>
      </tr>
      <tr>
        <td><code>controls</code>*</td>
        <td>Shows the default video controls (play, pause, etc)</td>
      </tr>
      <tr>
        <td><code>height</code> &amp; <code>width</code></td>
        <td>Sets the width and height of the video in CSS pixels</td>
      </tr>
      <tr>
        <td><code>loop</code>*</td>
        <td>Tells the browser to automatically loop the video</td>
      </tr>
      <tr>
        <td><code>muted</code>*</td>
        <td>Mutes the audio from the video</td>
      </tr>
    </tbody>
  </table>

  <p>
    *indicates a binary attribute, which enables that behavior when the
    attribute is present, or has it's value set to anything.
  </p>

  <h3 id="toc-styling">Styling</h3>

  <p>
    Because the <code>&lt;video&gt;</code> element is just another HTML 
    element, you can style it like any other element.  You can add borders,
    set the opacity, apply a filter or even do a 3D transform on the video.  
    For example, by applying <code>filter: grayscale(100%);</code> to the 
    video element, you can turn your video into a black and white video:
  </p>

  <video preload="metadata" controls style="width:640px;height:360px; -webkit-filter:grayscale(100%); -moz-filter:grayscale(100%); -ms-filter:grayscale(100%); filter:grayscale(100%);" poster="poster.png">
    <source src="devstories.webm" type='video/webm;codecs="vp8, vorbis"' />
    <source src="devstories.mp4" type='video/mp4;codecs="avc1.42E01E, mp4a.40.2"' />
    <track src="devstories-en.vtt" label="English subtitles" kind="subtitles" srclang="en" default></track>
  </video>

  <p class="notice warning">
    As of the January 2014, the filter effect is only supported in WebKit
    and Blink based browsers.
  </p>

  <h2 id="toc-javascript">JavaScript</h2>

  <p>
    Media elements like <code>&lt;video&gt;</code> and 
    <code>&lt;audio&gt;</code> have additional JavaScript functionality 
    beyond normal <code>HTMLElements</code> that allow you to interact or 
    control the media.  
  </p>

  <h3 id="toc-jsprop">Properties</h3>

  <table>
    <tbody>
      <tr>
        <td><code>currentTime</code></td>
        <td>Gets or sets the current playback position in seconds</td>
      </tr>
      <tr>
        <td><code>volume</code></td>
        <td>Gets or sets the current volume level for the video</td>
      </tr>
      <tr>
        <td><code>muted</code></td>
        <td>Gets or sets the mute state</td>
      </tr>
      <tr>
        <td><code>playbackRate</code></td>
        <td>Gets or sets the playback rate, where 1 is normal speed forward</td>
      </tr>
      <tr>
        <td><code>currentSrc</code></td>
        <td>Returns the current video source file the browser is playing</td>
      </tr>
      <tr>
        <td><code>videoWidth</code> &amp; <code>videoHeight</code></td>
        <td>Returns the actual dimensions of the video, not the video element size</td>
      </tr>
    </tbody>
  </table>

  <h3 id="toc-js-methods">Methods</h3>

  <table>
    <tbody>
      <tr>
        <td><code>load()</code></td>
        <td>Loads the video and reset the play head to the beginning of the video</td>
      </tr>
      <tr>
        <td><code>play()</code></td>
        <td>Plays the video from it’s current location</td>
      </tr>
      <tr>
        <td><code>pause()</code></td>
        <td>Pauses the video at the current location</td>
      </tr>
      <tr>
        <td><code>canPlayType(format)</code></td>
        <td>
          <p>
            Tests to see whether the browser can play a specific type of
            video, for example <code>'video/webm;codecs="vp8, vorbis"'</code>
          </p>
          <p>The browser will return:</p>
          <ul>
            <li><b><code>probably</code></b> - if it’s most likely the video file can be played</li>
            <li><b><code>maybe</code></b> - if the video might be playable</li>
            <li><b><code>[empty string]</code></b> - if the video file is not playable</li>
          </ul>
        </td>
      </tr>
    </tbody>
  </table>

  <h2>Events*</h2>

  <table>
    <tbody>
      <tr>
        <td><code>canplaythrough</code></td>
        <td>Fired when enough data is available that the browser believes it can play the video completely without interruption</td>
      </tr>
      <tr>
        <td><code>ended</code></td>
        <td>Fired when the video has finished playing</td>
      </tr>
      <tr>
        <td><code>error</code></td>
        <td>Fired if an error occurs</td>
      </tr>
      <tr>
        <td><code>playing</code></td>
        <td>Fired when the video starts playing, for the first time, after being paused or when restarting</td>
      </tr>
      <tr>
        <td><code>progress</code></td>
        <td>Fired periodically to indicate the progress of downloading the video</td>
      </tr>
      <tr>
        <td><code>waiting</code></td>
        <td>Fired when an action is delayed pending the completion of another action</td>
      </tr>
      <tr>
        <td><code>loadedmetadata</code></td>
        <td>Fired when the browser has finished loading the metadata for the video and all attributes have been populated</td>
      </tr>
    </tbody>
  </table>

  <p class="notice">
    These are only a subset of the media events that may be fired. Refer to 
    the <a href="https://developer.mozilla.org/docs/Web/Guide/Events/Media_events">
    Media events</a> page on the Mozilla Developer Network for a complete listing.
  </p>

  <p>
    There are many things that you can do using these JavaScript functions, 
    events and attributes; you can build your own set of rich video controls, 
    control multiple videos at the same time, jump to specific times within 
    the video and plenty more.  You can also use one of the many custom 
    player controls that are available today to provide a rich experience.
  </p>

  <h2 id="toc-interacting">Interacting with other elements</h2>

  <p>
    Video elements can interact with other elements like <code>canvas</code> 
    to provide a completely new experience.  <code>Canvas</code>' 
    <code>drawImage</code> lets you grab a single frame from the
    <code>video</code> element, and draw it within the <code>canvas</code>.
  </p>

<pre class="prettyprint"><code>function grabScreenshot() {
  ctx.drawImage(video, 0, 0, videoWidth, videoHeight);
  var img = new Image();
  img.src = canvas.toDataURL("image/png");
  img.width = 120;
  ssContainer.appendChild(img);
}</code></pre>

  <video controls id="vid4ss" style="width:640px;height:360px;">
    <source src="devstories.webm" type='video/webm;codecs="vp8, vorbis"' />
    <source src="devstories.mp4" type='video/mp4;codecs="avc1.42E01E, mp4a.40.2"' />
  </video>
  <div>
    <canvas id="canvas" style="display:none;"></canvas>
    <div id="screenShots"></div>
  </div>

  <script type="text/javascript">
    var video = document.getElementById("vid4ss");
    video.addEventListener("loadedmetadata", initScreenshot);
    video.addEventListener("playing", startScreenshot);
    video.addEventListener("pause", stopScreenshot);
    video.addEventListener("ended", stopScreenshot);


    var canvas = document.getElementById("canvas");
    var ctx = canvas.getContext("2d");
    var ssContainer = document.getElementById("screenShots");
    var videoHeight, videoWidth;
    var drawTimer = null;

    function initScreenshot() {
      console.log("Init Screenshot");
      videoHeight = video.videoHeight; 
      videoWidth = video.videoWidth;
      canvas.width = videoWidth;
      canvas.height = videoHeight;
    }

    function startScreenshot() {
      if (drawTimer == null) {
        drawTimer = setInterval(grabScreenshot, 1000);
      }
    }

    function stopScreenshot() {
      if (drawTimer) {
        clearInterval(drawTimer);
        drawTimer = null;
      }
    }

    function grabScreenshot() {
      ctx.drawImage(video, 0, 0, videoWidth, videoHeight);
      var img = new Image();
      img.src = canvas.toDataURL("image/png");
      img.width = 120;
      ssContainer.appendChild(img);
    }
  </script>

  <p>
    You can then modify the captured pixels and change the video in real time. 
    For example, you could provide your own 
    <a href="https://developer.mozilla.org/docs/HTML/Manipulating_video_using_canvas">
    chroma-key effect</a>, make the 
    <a href="http://craftymind.com/factory/html5video/CanvasVideo.html">video 
    explode</a> when you click on it, or 
    <a href="http://html5videoguide.net/code_c6_9.html">change the background 
    color</a> of the page based on the primary colors in the video.  
    The possibilities are almost limitless!
  </p>

  <p>
    The same technique of importing images can be also applied to WebGL. With 
    WebGL you can import the frames of a video and render them on a 
    <a href="https://developer.mozilla.org/docs/Web/WebGL/Animating_textures_in_WebGL">
    spinning 3D cube</a>.
  </p>

  <h2 id="toc-formats">Formats &amp; codecs</h2>

  <p>
    You can think of a video file as a container (like a ZIP file), that 
    contains the encoded video stream and an audio stream.  There are many 
    different types of container formats and unfortunately there isn't a 
    single 'one-ring' format that will work in all browsers.  If you're 
    wondering why you need to use two encodings, be sure to 
    read <a href="http://diveintohtml5.info/video.html#licensing">Licensing 
    issues with H.264 video</a>.
  </p>

  <p>
    Thankfully, we can get coverage for all modern (and mobile) browsers 
    using only two formats:
  </p>

  <ul>
    <li>
      <b><code>WebM</code></b> - uses the VP8 codec for video and the 
      Vorbis codec for audio
    </li>
    <li>
      <b><code>MP4</code></b> - uses the H.264 codec for video and the 
      AAC codec for audio
    </li>
  </ul>

  <p>
    WebM was designed specifically for serving video on the web, and has many 
    benefits.  Its low computational footprint means that it plays well on 
    high-end desktops but also on low-powered devices like tablets or phones.
    High compression rates for video, which means videos can be downloaded 
    faster, or you can improve the quality without a significant size increase.
    The encoding process is also significantly simpler with fewer profiles 
    and sub-options.
  </p>

  <p>
    Support for WebM is available natively in Chrome, Firefox and Opera, and 
    can be added to Internet Explorer or desktop Safari by installing a 
    plug-in.  When not available natively or if the plug-in isn't installed, 
    you'll need to provide the video encoded using the MP4 format.
  </p>

  <p>
    The <a href="http://diveintohtml5.info/video.html">video chapter</a> on 
    <a href="http://www.diveintohtml5.info">www.diveintohtml5.info</a> has 
    an excellent section on how best to encode your videos.  They recommend 
    using <a href="http://diveintohtml5.info/video.html#webm-cli">ffmpeg for 
    WebM</a> videos and 
    <a href="http://diveintohtml5.info/video.html#handbrake-gui">HandBrake for 
    MP4</a> videos.
  </p>

  <h2 id="toc-mobile">Mobile</h2>

  <p>
    Mobile provides some unique challenges for video.  Sending a 1080p 
    video to a mobile device like a phone doesn't make much sense, the 
    video will likely be too big for the screen, and the bandwidth required 
    to send the video may use all of the users limited data connection 
    extremely quickly.
  </p>

  <p>
    Browser vendors have accounted for this and have disabled the autoplay 
    and preload attributes on mobile devices.   It's also a good idea to 
    include poster image that can be displayed until playback begins, though 
    this does potentially require an additional download.  This gives 
    viewers a meaningful idea of content without needing to download video or 
    start playback.
  </p>

  <p class="notice tip hidden">
    <b>Learn more:</b> Check out <a href="#">Best practices 
    for video on the mobile web</a> for more information about video on
    mobile devices.
  </p>


  <h2 id="toc-further">Further Reading</h2>

  <h3 id="toc-eme">Encrypted Media Extensions - EME</h3>

  <p>
    Encrypted Media Extensions (sometimes referred to as EME) is a JavaScript
    API that enables web applications to interact with content protection 
    systems, in order to allow playback of 
    <a href="http://simpl.info/clearkey">encrypted audio and video</a>.  
    EME is an extension to the HTMLMediaElement specification, and browser 
    support is optional.  If a browser does not support EME, it will simply 
    silently fail to play the encrypted media.
  </p>

  <p class="notice tip hidden">
    To learn more about encrypted media extensions and how to play back videos 
    protected with them, check out <a href="">EME WTF?: 
    Encrypted Media Extensions 101.</a>
  </p>

  <h3 id="toc-streaming">Streaming video with the MediaSource API</h3>

  <p>
    The
    <a href="http://updates.html5rocks.com/2011/11/Stream-video-using-the-MediaSource-API">
    MediaSource API</a> extends the <code>HTMLMediaElement</code> to allow 
    JavaScript to generate media streams for playback. Allowing JavaScript to 
    generate streams facilitates a variety of use cases like adaptive 
    streaming and time shifting live streams.
  </p>

  <h2 id="toc-summary">Summary</h2>

  <p>
    Including video on the modern web is easier than ever before and opens 
    some amazing new possibilities.  What will you do next?
  </p>

{% endblock %}
